﻿#region Documentation
/*
 * Definition of the Payment entity
 *  
 * Copyright (C) 2014  Daniel Hamacher
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 * 
 * */
#endregion
using SpendingMonitor.Common;
using SpendingMonitor.Models;
using SpendingMonitor.ViewModels;
using Callisto.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Threading;

namespace SpendingMonitor.Views
{
    /// <summary>
    /// A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class NewPaymentPage : Page
    {
        #region Fields
        private PaymentViewModel payment;


        private NavigationHelper navigationHelper;
        private ObservableDictionary defaultViewModel = new ObservableDictionary();
        #endregion

        #region Bootstrap
        public NewPaymentPage()
        {
            this.InitializeComponent();
            populateUiData();
            populateComboBoxData();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;
            this.navigationHelper.SaveState += navigationHelper_SaveState;
        }


        /// <summary>
        /// Fill the UI element with default values so the user knows what the combo box is used for.
        /// </summary>
        private void populateUiData()
        {
            using (var db = new SQLite.SQLiteConnection(SpendingMonitor.App.DBPath))
            {
                if (db.Table<Category>().ToList().Count == 0)
                {
                    db.Insert(new Category()
                    {
                        Name = "Gas"
                    });
                }
                if (db.Table<Retailer>().ToList().Count == 0)
                {
                    db.Insert(new Retailer()
                        {
                            Name = "7eleven",
                            GroupedBy = "Gas"
                        });
                }
                if (db.Table<PaymentMethod>().ToList().Count == 0)
                {
                    db.Insert(new PaymentMethod()
                        {
                            Name = "Interac"
                        });
                }
            }
        }

        private void populateComboBoxData()
        {
            using (var db = new SQLite.SQLiteConnection(SpendingMonitor.App.DBPath))
            {
                List<Category> categories = db.Table<Category>().ToList();
                foreach (var item in categories)
                {
                    this.Category.Items.Add(item.Name);
                    this.Category.SelectedIndex = 0;
                }
                List<PaymentMethod> paymentMethods = db.Table<PaymentMethod>().ToList();
                foreach (var item in paymentMethods)
                {
                    this.PaymentMethod.Items.Add(item.Name);
                    this.PaymentMethod.SelectedIndex = 0;
                }
            }
        }
        #endregion

        #region callisto:Custom Dialog Save Event
        private void SaveNewPropertyFromDialogButton_Click(object sender, RoutedEventArgs e)
        {
            if ((this.NewPropertyDialog.Title.Equals("New Category")
                && !this.RetailValue.Text.Equals(String.Empty)
                && !this.Value.Text.Equals(String.Empty)))
            {
                Category c;
                Retailer r;
                using (var db = new SQLite.SQLiteConnection(SpendingMonitor.App.DBPath))
                {
                    db.Insert(c = new Category()
                    {
                        Name = this.Value.Text
                    });
                    db.Insert(r = new Retailer()
                    {
                        Name = this.RetailValue.Text,
                        GroupedBy = this.Value.Text
                    });
                }
                this.NewPropertyDialog.IsOpen = false;
                this.Value.Text = String.Empty;
                this.RetailValue.Text = String.Empty;
                this.Category.Items.Add(c.Name);
                this.Category.SelectedItem = c.Name;
            }
            else if (this.NewPropertyDialog.Title.Equals("Add Retailer") && !this.Value.Text.Equals(String.Empty))
            {
                Retailer r;
                string groupeName = Category.SelectedItem as String;
                this.Instruction.Text = "Add a Retailer for " + groupeName;
                using (var db = new SQLite.SQLiteConnection(SpendingMonitor.App.DBPath))
                {
                    db.Insert(r = new Retailer()
                        {
                            Name = this.Value.Text,
                            GroupedBy = groupeName
                        });
                }
                this.NewPropertyDialog.IsOpen = false;
                this.Value.Text = String.Empty;
                this.Retailer.Items.Add(r.Name);
                this.Retailer.SelectedItem = r.Name;
            }
            else if (this.NewPropertyDialog.Title.Equals("New Payment Method") && !this.Value.Text.Equals(String.Empty))
            {
                PaymentMethod p;
                using (var db = new SQLite.SQLiteConnection(SpendingMonitor.App.DBPath))
                {
                    db.Insert(p = new PaymentMethod()
                        {
                            Name = this.Value.Text
                        });
                }
                this.NewPropertyDialog.IsOpen = false;
                this.Value.Text = String.Empty;
                this.PaymentMethod.Items.Add(p.Name);
                this.PaymentMethod.SelectedItem = p.Name;
            }
            else
            {
                /* THe border are changed to indicate that data is missing. Those borders will 
                 * be removed when calling the NewPropertyButton_Click event to reset its initial state. */
                SolidColorBrush borderBrush = new SolidColorBrush(Windows.UI.Colors.Red);
                if (this.Value.Text.Equals(String.Empty))
                {
                    this.Value.BorderBrush = borderBrush;
                }
                if (this.RetailValue.Text.Equals(String.Empty))
                {
                    this.RetailValue.BorderBrush = borderBrush;
                }
                App.Prompt("Some value is missing");
            }
        }
        #endregion

        #region Page Events
        private void NewPropertyButton_Click(object sender, RoutedEventArgs e)
        {
            this.RetailValue.BorderBrush = null;// backgroundBrush;
            this.Value.BorderBrush = null;// backgroundBrush;           
            Button btn = sender as Button;
            if (ReferenceEquals(btn, null))
            {
                //TODO: Log the error
            }
            else if (btn.Content.Equals("New Category"))
            {
                this.RetailInstruction.Visibility = Visibility.Visible;
                this.RetailValue.Visibility = Visibility.Visible;
                this.NewPropertyDialog.Title = "New Category";
                this.Instruction.Text = "Enter a new Category";
                this.RetailInstruction.Text = "Add a retailer for this Category";
                this.NewPropertyDialog.IsOpen = true;
            }
            else if (btn.Content.Equals("Add Retailer"))
            {
                this.NewPropertyDialog.Title = "Add Retailer";
                this.Instruction.Text = "Add a Retailer for: " + (Category.SelectedItem as String);
                this.NewPropertyDialog.IsOpen = true;
                this.RetailInstruction.Visibility = Visibility.Collapsed;
                this.RetailValue.Visibility = Visibility.Collapsed;
            }
            else if (btn.Content.Equals("New Payment Method"))
            {
                this.NewPropertyDialog.Title = "New Payment Method";
                this.Instruction.Text = "Enter a Payment Method";
                this.NewPropertyDialog.IsOpen = true;
                this.RetailInstruction.Visibility = Visibility.Collapsed;
                this.RetailValue.Visibility = Visibility.Collapsed;
            }
        }

        private void SaveNewPaymentButton_Click(object sender, RoutedEventArgs e)
        {
            if (Price.Value <= 0)
            {
                SpendingMonitor.App.Prompt("The value for the price cannot be 0. Try Again");
            }
            else
            {
                payment = new PaymentViewModel()
                {
                    Category = this.Category.SelectedItem as String,
                    Retailer = this.Retailer.SelectedItem as String,
                    PaymentMethod = this.PaymentMethod.SelectedItem as String,
                    PayedOn = this.PayedOn.Date.DateTime,
                    Price = this.Price.Value
                };
                string result = payment.SaveEntry(payment);
                if (result.Contains("Success"))
                {
                    this.Frame.Navigate(typeof(MainPage));
                }
            }
        }

        /// <summary>
        /// When the selection on the category changes, then the collection of the retailers changes accordingly,
        /// so you don't end up buying Gas at Old Navy :)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Category_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Retailer.Items.Clear();
            string category = Category.SelectedItem as String;
            using (var db = new SQLite.SQLiteConnection(App.DBPath))
            {
                List<Retailer> retailers = db.Table<Retailer>().ToList();
                List<String> retailerByGroup = retailers.Where(x => x.GroupedBy.Equals(category)).Select(x => x.Name).ToList();
                foreach (string s in retailerByGroup)
                {
                    Retailer.Items.Add(s);
                    Retailer.SelectedIndex = 0;
                }
            }
        }

        #endregion

        #region Default View Model
        /// <summary>
        /// This can be changed to a strongly typed view model.
        /// </summary>
        public ObservableDictionary DefaultViewModel
        {
            get { return this.defaultViewModel; }
        }
        #endregion

        #region Navigation Helper
        /// <summary>
        /// NavigationHelper is used on each page to aid in navigation and 
        /// process lifetime management
        /// </summary>
        public NavigationHelper NavigationHelper
        {
            get { return this.navigationHelper; }
        }

        /// <summary>
        /// Populates the page with content passed during navigation. Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="sender">
        /// The source of the event; typically <see cref="NavigationHelper"/>
        /// </param>
        /// <param name="e">Event data that provides both the navigation parameter passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
        /// a dictionary of state preserved by this page during an earlier
        /// session. The state will be null the first time a page is visited.</param>
        private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) { }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="sender">The source of the event; typically <see cref="NavigationHelper"/></param>
        /// <param name="e">Event data that provides an empty dictionary to be populated with
        /// serializable state.</param>
        private void navigationHelper_SaveState(object sender, SaveStateEventArgs e) { }
        #endregion

        #region NavigationHelper registration

        /// The methods provided in this section are simply used to allow
        /// NavigationHelper to respond to the page's navigation methods.
        /// 
        /// Page specific logic should be placed in event handlers for the  
        /// <see cref="GridCS.Common.NavigationHelper.LoadState"/>
        /// and <see cref="GridCS.Common.NavigationHelper.SaveState"/>.
        /// The navigation parameter is available in the LoadState method 
        /// in addition to page state preserved during an earlier session.

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
        }
        #endregion
    }
}
